//
// Created by 202207384 on 2022/9/28.
//

#include <vector>
#include <cstring>
#include <iostream>
#include "dat_parser.h"
#include "public_define.h"

#include "encode_srv.pb.h"

/* check frame head if 0000 0001 then h265 I frame*/
#define CODEC_PROBE_H265_I_FRAME(data) (0x0 == ((char *)data)[0] && 0x0 == ((char *)data)[1] && 0x0 == ((char *)data)[2] && 0x1 == ((char *)data)[3] && 0x40 ==((char *)data)[4])

DatParser::DatParser()
{
}

DatParser::~DatParser()
{
}

void DatParser::parse(const string &filePath, std::vector<DatParser::ReplayData> &repVec)
{
    ifstream ifs;
    ifs.open(filePath);
    if (!ifs.is_open())
    {
        Log_ERROR("fail to open file: {}", filePath);
        return;
    }

    ifs.seekg(0, ios_base::beg);
    doParse(ifs, repVec);
    ifs.close();
}

void DatParser::parse_forEdc(const string &filePath, SocketData &sdh32, SocketData &sdh16, SocketData &sdh8, 
                                                    SocketData &sdh4, SocketData &sdh2, SocketData &sdh1)
{
    ifstream ifs;
    ifs.open(filePath);
    if (!ifs.is_open())
    {
        Log_ERROR("fail to open file: {}", filePath);
        return;
    }
    ifs.seekg(0, ios_base::beg);

    doParse_forEdc(ifs, sdh32, sdh16, sdh8, sdh4, sdh2, sdh1);
    ifs.close();
}

void DatParser::doParse(ifstream &ifs, std::vector<ReplayData> &repVec)
{
    //解析文件头
    FileHead fileHead;
    ifs.read((char *)&fileHead, sizeof(fileHead));

    if (fileHead.protoContentSize > 0)
    {
        string protoContent;
        protoContent.resize(fileHead.protoContentSize);
        ifs.read(&protoContent[0], fileHead.protoContentSize);
        // todo 解析proto
    }

    if (fileHead.commentLength > 0)
    {
        std::string comment;
        comment.resize(fileHead.commentLength);
        ifs.read(&comment[0], fileHead.commentLength);
    }

    ReplayData replayData;
    while (ifs.read((char *)&replayData.head, sizeof(replayData.head)))
    {
        std::string topic(replayData.head.name);
        topic = DcAdr::Util::deletSDAHead(topic);
        memset(replayData.head.name, 0, strlen(replayData.head.name));
        memcpy(replayData.head.name, topic.c_str(), topic.size());

        // Log_Info("ReplayData: {} size: {}  time: {}", std::string(replayData.head.name), replayData.head.size, replayData.head.timestamp);
        size_t size = replayData.head.size;

        replayData.data.resize(size);
        ifs.read(&replayData.data[0], size);

        repVec.push_back(replayData);
    }

    ifs.close();
}

void DatParser::doParse_forEdc(ifstream &ifs, SocketData &sdh32, SocketData &sdh16, SocketData &sdh8, 
                                                SocketData &sdh4, SocketData &sdh2, SocketData &sdh1)
{
    //解析文件头
    FileHead fileHead;
    ifs.read((char *)&fileHead, sizeof(fileHead));

    if (fileHead.protoContentSize > 0)
    {
        string protoContent;
        protoContent.resize(fileHead.protoContentSize);
        ifs.read(&protoContent[0], fileHead.protoContentSize);
        // todo 解析proto
    }

    if (fileHead.commentLength > 0)
    {
        std::string comment;
        comment.resize(fileHead.commentLength);
        ifs.read(&comment[0], fileHead.commentLength);
    }

    ReplayData replayData;
    while (ifs.read((char *)&replayData.head, sizeof(replayData.head)))
    {
        std::string topic(replayData.head.name);
        topic = DcAdr::Util::deletSDAHead(topic);
        memset(replayData.head.name, 0, strlen(replayData.head.name));
        memcpy(replayData.head.name, topic.c_str(), topic.size());

        // Log_Info("ReplayData: {} size: {}  time: {}", std::string(replayData.head.name), replayData.head.size, replayData.head.timestamp);
        size_t size = replayData.head.size;

        replayData.data.resize(size);
        ifs.read(&replayData.data[0], size);

        /******************************/

        EncodeSrv::EncodeH265 enc;
        uint64_t dataTime = replayData.head.timestamp * 1000;
        if (!enc.ParsePartialFromString(replayData.data))
        {
            Log_ERROR("EncodeSrv::EncodeH265 ParsePartialFromString error, topic: {}, end", topic);
            continue;
        }
        if (enc.frame_data().size() == 0)
        {
            Log_ERROR("h265Data size is 0");
            continue;
        }
        if (enc.encode_width() != 1920 || enc.encode_height() != 1080)
        {
            // Log_ERROR("h265Data is not 1920*1080");
            continue;
        }

        if (ENCODE_SRV_H265_CAM0 == topic)
        {
            if (0 == sdh32.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh32.header.startFrameTimeStamp = dataTime;

                    sdh32.header.camera = 0x20;
                    sdh32.header.endFrameTimeStamp = dataTime;
                    sdh32.header.fileSize += enc.frame_data().length();
                    sdh32.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh32.header.camera = 0x20;
                sdh32.header.endFrameTimeStamp = dataTime;
                sdh32.header.fileSize += enc.frame_data().length();
                sdh32.data.push_back(enc.frame_data());
            }
        }
        if (ENCODE_SRV_H265_CAM1 == topic)
        {
            if (0 == sdh16.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh16.header.startFrameTimeStamp = dataTime;

                    sdh16.header.camera = 0x10;
                    sdh16.header.endFrameTimeStamp = dataTime;
                    sdh16.header.fileSize += enc.frame_data().length();
                    sdh16.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh16.header.camera = 0x10;
                sdh16.header.endFrameTimeStamp = dataTime;
                sdh16.header.fileSize += enc.frame_data().length();
                sdh16.data.push_back(enc.frame_data());
            }
        }
        if (ENCODE_SRV_H265_CAM3 == topic)
        {
            if (0 == sdh8.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh8.header.startFrameTimeStamp = dataTime;

                    sdh8.header.camera = 0x8;
                    sdh8.header.endFrameTimeStamp = dataTime;
                    sdh8.header.fileSize += enc.frame_data().length();
                    sdh8.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh8.header.camera = 0x8;
                sdh8.header.endFrameTimeStamp = dataTime;
                sdh8.header.fileSize += enc.frame_data().length();
                sdh8.data.push_back(enc.frame_data());
            }
        }
        if (ENCODE_SRV_H265_CAM2 == topic)
        {
            if (0 == sdh4.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh4.header.startFrameTimeStamp = dataTime;

                    sdh4.header.camera = 0x4;
                    sdh4.header.endFrameTimeStamp = dataTime;
                    sdh4.header.fileSize += enc.frame_data().length();
                    sdh4.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh4.header.camera = 0x4;
                sdh4.header.endFrameTimeStamp = dataTime;
                sdh4.header.fileSize += enc.frame_data().length();
                sdh4.data.push_back(enc.frame_data());
            }
        }
        if (ENCODE_SRV_H265_CAM10 == topic)
        {
            if (0 == sdh2.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh2.header.startFrameTimeStamp = dataTime;

                    sdh2.header.camera = 0x2;
                    sdh2.header.endFrameTimeStamp = dataTime;
                    sdh2.header.fileSize += enc.frame_data().length();
                    sdh2.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh2.header.camera = 0x2;
                sdh2.header.endFrameTimeStamp = dataTime;
                sdh2.header.fileSize += enc.frame_data().length();
                sdh2.data.push_back(enc.frame_data());
            }
        }
        if (ENCODE_SRV_H265_CAM8 == topic)
        {
            if (0 == sdh1.header.startFrameTimeStamp)
            {
                if (CODEC_PROBE_H265_I_FRAME(enc.frame_data().c_str()))
                {
                    sdh1.header.startFrameTimeStamp = dataTime;

                    sdh1.header.camera = 0x1;
                    sdh1.header.endFrameTimeStamp = dataTime;
                    sdh1.header.fileSize += enc.frame_data().length();
                    sdh1.data.push_back(enc.frame_data());
                }
                else
                {
                    continue;
                }
            }
            else
            {
                sdh1.header.camera = 0x1;
                sdh1.header.endFrameTimeStamp = dataTime;
                sdh1.header.fileSize += enc.frame_data().length();
                sdh1.data.push_back(enc.frame_data());
            }
        }
    }

    ifs.close();
}
